package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.OrderService;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import com.sky.websocket.WebSocketServer;
import io.swagger.annotations.ApiOperation;
import org.aspectj.weaver.ast.Or;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private WebSocketServer webSocketServer;


    /**
     * c端-用户下单
     * @param ordersSubmitDTO
     * @return
     */
    @Transactional
    public OrderSubmitVO save(OrdersSubmitDTO ordersSubmitDTO){
        Long userId = BaseContext.getCurrentId();
        // 处理地址簿异常
        AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
        if (addressBook == null){
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        // 处理购物车异常
        ShoppingCart shoppingCart = new ShoppingCart();
        shoppingCart.setUserId(userId);
        List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
        if (list == null || list.size() == 0){
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }
        // 添加orders主体
        // 构造参数
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO,orders);
        orders.setNumber(UUID.randomUUID().toString());
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setUserId(userId);
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);
        orders.setPhone(addressBook.getPhone());
        orders.setConsignee(addressBook.getConsignee());
        ordersMapper.insert(orders);
        // 批量添加order_detail信息
        Long orderId = orders.getId();
        List<OrderDetail> orderDetailList = list.stream().map(item -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setName(item.getName());
            BeanUtils.copyProperties(item, orderDetail, "id");
            orderDetail.setOrderId(orderId);
            return orderDetail;
        }).collect(Collectors.toList());
        orderDetailMapper.insertBatch(orderDetailList);
        // 清空购物车
        shoppingCartMapper.deleteAllByUserId(userId);
        //返回vo
        OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
                .id(orderId)
                .orderNumber(orders.getNumber())
                .orderAmount(ordersSubmitDTO.getAmount())
                .orderTime(orders.getOrderTime())
                .build();
        return orderSubmitVO;
    }

    /**
     * c端-订单支付
     * @param ordersPaymentDTO
     * @return
     */
    public int pay(OrdersPaymentDTO ordersPaymentDTO){
        Orders orders = Orders.builder()
                .number(ordersPaymentDTO.getOrderNumber())
                .status(Orders.TO_BE_CONFIRMED)
                .checkoutTime(LocalDateTime.now())
                .payMethod(ordersPaymentDTO.getPayMethod())
                .payStatus(Orders.PAID)
                .build();
        int row = ordersMapper.update(orders);
        // 支付成功,通过websocket通知管理端
        HashMap<String, Object> map = new HashMap<>();
        map.put("type",1);// 来单提醒
        map.put("orderId",orders.getId());
        map.put("content","订单号："+orders.getNumber());
        String jsonMsg = JSON.toJSONString(map);
        webSocketServer.sendToAllClient(jsonMsg);
        return row;
    }

    /**
     * c端-查询订单详情
     * @param id
     * @return
     */
    public OrderVO getInfo(Long id){
        Orders orders = ordersMapper.getById(id);
        List<OrderDetail> list = orderDetailMapper.listByOrders(orders);
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(orders,orderVO);
        orderVO.setOrderDetailList(list);
        return orderVO;
    }

    /**
     * c端-历史订单查询
     * @param ordersPageQueryDTO
     * @return
     */
    public PageResult pageQuery(OrdersPageQueryDTO ordersPageQueryDTO){
        Long userId = BaseContext.getCurrentId();
        //构造参数
        ordersPageQueryDTO.setUserId(userId);
        PageHelper.startPage(ordersPageQueryDTO.getPage(),ordersPageQueryDTO.getPageSize());
        Page<Orders> page = ordersMapper.pageQuery(ordersPageQueryDTO);
        long total = page.getTotal();
        List<Orders> records = page.getResult();
        // 查询并拼接中间表数据
        records = records.stream().map(item -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(item, orderVO);
            // 拼接参数
            Orders orders = new Orders();
            orders.setId(item.getId());
            List<OrderDetail> list = orderDetailMapper.listByOrders(orders);
            orderVO.setOrderDetailList(list);
            return orderVO;
        }).collect(Collectors.toList());

        return new PageResult(total,records);
    }

    /**
     * c端-用户取消订单
     * @param id
     * @return
     */
    public void userCancel(Long id){
        Orders orders = ordersMapper.getById(id);
        // 订单不存在
        if (orders == null){
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        Integer payStatus = orders.getPayStatus();
        // 订单已接单,不可取消
        if (payStatus > 3){
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        Orders ordersDB = new Orders();
        // 订单待接单,取消+退款
        if (payStatus.equals(Orders.TO_BE_CONFIRMED)){
            // 退款
            ordersDB.setPayStatus(Orders.REFUND);
        }
        // 订单未支付
        ordersDB.setId(id);
        ordersDB.setStatus(Orders.CANCELLED);
        ordersDB.setCancelReason("用户取消");
        ordersDB.setCancelTime(LocalDateTime.now());
        ordersMapper.update(ordersDB);
    }

    /**
     * c端-再来一单
     * @param id
     */
    public int repetition(Long id){
        Orders orders = new Orders();
        orders.setId(id);
        List<OrderDetail> list = orderDetailMapper.listByOrders(orders);
        Long userId = BaseContext.getCurrentId();
        List<ShoppingCart> shoppingCartList = list.stream().map(item -> {
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(item, shoppingCart);
            shoppingCart.setUserId(userId);
            shoppingCart.setCreateTime(LocalDateTime.now());
            return shoppingCart;
        }).collect(Collectors.toList());
        return shoppingCartMapper.insertBatch(shoppingCartList);
    }

    /**
     * c端-催单
     * @param id
     */
    public void reminder(Long id){
        Orders orders = ordersMapper.getById(id);
        // 通过websocket向管理端发送用户催单消息
        HashMap<String, Object> map = new HashMap<>();
        map.put("type",2);// 用户催单
        map.put("orderId",orders.getId());
        map.put("content","订单号："+orders.getNumber());
        String jsonMsg = JSON.toJSONString(map);
        webSocketServer.sendToAllClient(jsonMsg);
    }

    /**
     * 订单搜索（分页）
     * @param ordersPageQueryDTO
     * @return
     */
    public PageResult pageQueryAll(OrdersPageQueryDTO ordersPageQueryDTO){
        //构造参数
        PageHelper.startPage(ordersPageQueryDTO.getPage(),ordersPageQueryDTO.getPageSize());
        Page<Orders> page = ordersMapper.pageQuery(ordersPageQueryDTO);
        long total = page.getTotal();
        List<Orders> records = page.getResult();
        // 查询并拼接中间表数据
        records = records.stream().map(item -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(item, orderVO);
            // 拼接参数
            Orders orders = new Orders();
            orders.setId(item.getId());
            List<OrderDetail> list = orderDetailMapper.listByOrders(orders);
            orderVO.setOrderDetailList(list);
            return orderVO;
        }).collect(Collectors.toList());

        return new PageResult(total,records);
    }

    /**
     * 各个状态的订单数量统计
     * @return
     */
    public OrderStatisticsVO statistics(){
        Integer toBeConfirmed = ordersMapper.getCountByStatus(Orders.TO_BE_CONFIRMED);
        Integer confirmed = ordersMapper.getCountByStatus(Orders.CONFIRMED);
        Integer deliveryInProgress = ordersMapper.getCountByStatus(Orders.DELIVERY_IN_PROGRESS);
        // 构造参数
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
        orderStatisticsVO.setConfirmed(confirmed);
        orderStatisticsVO.setDeliveryInProgress(deliveryInProgress);

        return orderStatisticsVO;
    }


    /**
     * 接单
     * @param ordersConfirmDTO
     */
    public int confirm(OrdersConfirmDTO ordersConfirmDTO){
        // 构造参数
        Orders orders = new Orders();
        orders.setId(ordersConfirmDTO.getId());
        orders.setStatus(Orders.CONFIRMED);
        return ordersMapper.update(orders);
    }

    /**
     * 拒单
     * @param ordersRejectionDTO
     */
    public void rejection(OrdersRejectionDTO ordersRejectionDTO){
        Long id = ordersRejectionDTO.getId();
        Orders orders = ordersMapper.getById(id);
        Integer status = orders.getStatus();
        // orders为空、当前status不为待接单时，抛异常
        if (orders == null || !status.equals(Orders.TO_BE_CONFIRMED)){
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        // 已支付，需要退款
        Orders ordersDB = new Orders();
        Integer payStatus = orders.getPayStatus();
        if (payStatus.equals(Orders.PAID)){
            ordersDB.setPayMethod(Orders.REFUND);
        }
        // 构造参数
        ordersDB.setId(id);
        ordersDB.setStatus(Orders.CANCELLED);
        ordersDB.setRejectionReason(ordersRejectionDTO.getRejectionReason());
        ordersDB.setCancelTime(LocalDateTime.now());

        ordersMapper.update(ordersDB);
    }

    /**
     * 取消订单
     * @param ordersCancelDTO
     */
    public void adminCancel(OrdersCancelDTO ordersCancelDTO){
        Long id = ordersCancelDTO.getId();
        Orders orders = ordersMapper.getById(id);
        // 订单不存在
        if (orders == null){
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        Integer payStatus = orders.getPayStatus();

        Orders ordersDB = new Orders();
        // 订单待接单,取消+退款
        if (payStatus.equals(Orders.TO_BE_CONFIRMED)){
            // 退款
            ordersDB.setPayStatus(Orders.REFUND);
        }
        // 订单未支付,构造参数
        ordersDB.setId(id);
        ordersDB.setStatus(Orders.CANCELLED);
        String cancelReason = ordersCancelDTO.getCancelReason();
        ordersDB.setCancelReason(cancelReason);
        ordersDB.setCancelTime(LocalDateTime.now());

        ordersMapper.update(ordersDB);
    }

    /**
     * 派送订单
     * @param id
     * @return
     */
    public int delivery(Long id){
        Orders orders = ordersMapper.getById(id);
        Integer status = orders.getStatus();
        // 订单不存在和不是已接单的状态
        if (orders == null || !status.equals(Orders.CONFIRMED)){
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        // 构造参数
        Orders ordersDB = new Orders();
        ordersDB.setId(id);
        ordersDB.setStatus(Orders.DELIVERY_IN_PROGRESS);
        return ordersMapper.update(ordersDB);
    }

    /**
     * 完成订单
     * @param id
     * @return
     */
    public int complete(Long id){
        Orders orders = ordersMapper.getById(id);
        Integer status = orders.getStatus();
        // 订单不存在和不是派送中的状态
        if (orders == null || !status.equals(Orders.DELIVERY_IN_PROGRESS)){
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        // 构造参数
        Orders ordersDB = new Orders();
        ordersDB.setId(id);
        ordersDB.setStatus(Orders.COMPLETED);
        return ordersMapper.update(ordersDB);
    }
}
